#include "CCursorControl.h"
#include "WinDevice.h"
#include <windowsx.h>

ldx::device::CCursorControl::CCursorControl(WinDevice * device, const mt::dimension2du & wsize, HWND hwnd, bool fullscreen)
	: Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f),
	HWnd(hwnd), BorderX(0), BorderY(0),
	UseReferenceRect(false), IsVisible(true)
	, ActiveIcon(ECI_NORMAL), ActiveIconStartTime(0)
{
	if (WindowSize.Width != 0)
		InvWindowSize.Width = 1.0f / WindowSize.Width;

	if (WindowSize.Height != 0)
		InvWindowSize.Height = 1.0f / WindowSize.Height;

	updateBorderSize(fullscreen, false);
	initCursors();
}

ldx::device::CCursorControl::~CCursorControl()
{
	for (unsigned int i = 0; i < Cursors.size(); ++i)
	{
		for (unsigned int f = 0; f < Cursors[i].Frames.size(); ++f)
		{
			DestroyCursor(Cursors[i].Frames[f].IconHW);
		}
	}
}

void ldx::device::CCursorControl::setActiveIcon(ECURSOR_ICON iconId)

{
	if (iconId >= (int)Cursors.size())
		return;

	ActiveIcon = iconId;
	ActiveIconStartTime = Device->getTimer()->getTimeCycles();
	if (Cursors[ActiveIcon].Frames.size())
		SetCursor(Cursors[ActiveIcon].Frames[0].IconHW);
}

mt::dimension2di ldx::device::CCursorControl::getSupportedIconSize() const

{
	mt::dimension2di result;

	result.Width = GetSystemMetrics(SM_CXCURSOR);
	result.Height = GetSystemMetrics(SM_CYCURSOR);

	return result;
}

void ldx::device::CCursorControl::update()

{
	if (!Cursors[ActiveIcon].Frames.empty() && Cursors[ActiveIcon].FrameTime)
	{
		// update animated cursors. This could also be done by X11 in case someone wants to figure that out (this way was just easier to implement)
		unsigned int now = Device->getTimer()->getTimeCycles();
		unsigned int frame = ((now - ActiveIconStartTime) / Cursors[ActiveIcon].FrameTime) % Cursors[ActiveIcon].Frames.size();
		SetCursor(Cursors[ActiveIcon].Frames[frame].IconHW);
	}
}

void ldx::device::CCursorControl::updateInternalCursorPosition()
{
	POINT p;
	if (!GetCursorPos(&p))
	{
		DWORD xy = GetMessagePos();
		p.x = GET_X_LPARAM(xy);
		p.y = GET_Y_LPARAM(xy);
	}

	if (UseReferenceRect)
	{
		CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;
		CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;
	}
	else
	{
		RECT rect;
		if (GetWindowRect(HWnd, &rect))
		{
			CursorPos.X = p.x - rect.left - BorderX;
			CursorPos.Y = p.y - rect.top - BorderY;
		}
		else
		{
			// window seems not to be existent, so set cursor to
			// a negative value
			CursorPos.X = -1;
			CursorPos.Y = -1;
		}
	}
}

void ldx::device::CCursorControl::initCursors()
{
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_ARROW)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_CROSS)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_HAND)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_HELP)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_IBEAM)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_NO)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_WAIT)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_SIZEALL)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_SIZENESW)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_SIZENWSE)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_SIZENS)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_SIZEWE)));
	Cursors.push_back(CursorW32(LoadCursor(NULL, IDC_UPARROW)));
}
